<?php

/*
 * Object/XRules.php
 */

namespace RHX\Model\Object;

use Zend\Db\Adapter\Adapter;
use RHX\Helper\RHDateTime;
use RHX\Model\Object\XData;
use Zend\Log\Logger;
use Zend\Log\Writer\Stream;

class XRules {

    private $rules;
    protected $adapter;

    /**
     * Logger
     *
     * @var Logger
     */
    private $logger;

    const Inconnue			 = 0;
    const Present				 = 1;
    const CongePaye			 = 2;
    const NeTravaillePas			 = 3;
    const Indisponible			 = 4;
    const Absent				 = 5;
    const CongeSansSolde			 = 6;
    const TransfertEntrant		 = 7;
    const TransfertSortant			 = 8;
    const ArretMaladie1			 = 9;
    const ArretMaladie2			 = 10;
    const AccidentTravail			 = 11;
    const EcoleFormation			 = 12;
    const Ferie1				 = 13;
    const Ferie2				 = 14;
    const Fermer				 = 15;
    const CongeMaternite			 = 16;
    const DepartAnticipe			 = 17;
    const Retard				 = 18;
    const ProblemeRetardDepartAnticipe	 = 19;
    const CongePayeExceptionnel		 = 20;
    const CongeMaternitePere		 = 21;
    const EcoleFormationIntegration	 = 22;
    const EcoleFormationEmploye		 = 23;
    const EcoleFormationAlternance	 = 24;
    const Ferie3				 = 25;
    const EntreeSortie			 = 26;

    /**
     * Constructeur
     *
     * @param \Zend\Db\Adapter\Adapter $adapter
     */
    public function __construct(Adapter $adapter) {
	$this->adapter	 = $adapter;
//	$this->logger	 = new Logger();
//	$writer		 = new Stream('module/RHX/logs/log-XRules-' . date('Y-m-d') . '.txt');
//	$this->logger->addWriter($writer);
//	$this->logger->info("############");
	$this->rules	 = array(
	    // Inconnue
	    self::Inconnue				 => array(
		'compte'	 => false,
		'paye'		 => 0.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // P : Présent
	    self::Present				 => array(
		'compte'	 => true,
		'paye'		 => 1.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // CP : Congés Paye
	    self::CongePaye				 => array(
		'compte'	 => true,
		'paye'		 => 1.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // OFF : Ne Travaille Pas
	    self::NeTravaillePas			 => array(
		'compte'	 => false,
		'paye'		 => 0.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // IND : Indisponible
	    self::Indisponible			 => array(
		'compte'	 => false,
		'paye'		 => 0.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // ABS : Absence Injustifié
	    self::Absent				 => array(
		'compte'	 => false,
		'paye'		 => 1.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => true,
	    ),
	    // CSS : Congé sans Solde
	    self::CongeSansSolde			 => array(
		'compte'	 => false,
		'paye'		 => 0.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // TE : Transfert Entrant
	    self::TransfertEntrant			 => array(
		'compte'	 => true,
		'paye'		 => 1.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // TS : Transfert Sortant
	    self::TransfertSortant			 => array(
		'compte'	 => true,
		'paye'		 => 1.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // AM1 : Arrêt Maladie
	    self::ArretMaladie1			 => array(
		'compte'	 => true,
		'paye'		 => 1.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // AM2 : Arrêt Maladie supérieur à 1 An
	    self::ArretMaladie2			 => array(
		'compte'	 => true,
		'paye'		 => 1.0,
		'anciennete'	 => 1,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // AT : Accident Travaill
	    self::AccidentTravail			 => array(
		'compte'	 => true,
		'paye'		 => 1.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // EF : Ecole Formation
	    self::EcoleFormation			 => array(
		'compte'	 => true,
		'paye'		 => 1.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // F1 : Férié 1
	    self::Ferie1				 => array(
		'compte'	 => true,
		'paye'		 => 1.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // F2 : Férié 2
	    self::Ferie2				 => array(
		'compte'	 => true,
		'paye'		 => 2.0,
		'anciennete'	 => 1,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // F : Fermé
	    self::Fermer				 => array(
		'compte'	 => false,
		'paye'		 => 0.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // CM : Congé Maternité
	    self::CongeMaternite			 => array(
		'compte'	 => true,
		'paye'		 => 1.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // DA : Départ Anticipé
	    self::DepartAnticipe			 => array(
		'compte'	 => false,
		'paye'		 => 1.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // RT : Retard
	    self::Retard				 => array(
		'compte'	 => true,
		'paye'		 => 1.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	    // PRDA : Problème Retard Départ Anticipé
	    self::ProblemeRetardDepartAnticipe	 => array(
		'compte'	 => true,
		'paye'		 => 1.0,
		'anciennete'	 => 0,
		'pause'		 => false,
		'repas'		 => false,
	    ),
	);
    }

    /**
     * Tableau des règles
     *
     * @param int $id
     * @return type
     */
    public function getRule($id) {
	return (isset($this->rules[$id])) ? $this->rules[$id] : $this->rules[0];
    }

    /**
     * Code Comptabilité ou non
     *
     * @param int $id
     * @return Boolean
     */
    public function isCountable($id) {
	$rules = $this->getRule($id);

	return $rules['compte'];
    }

    /**
     * Coefficient de Paye
     * 
     * @param int $id
     * @return float
     */
    public function getPaye($id) {
	$rules = $this->getRule($id);

	return $rules['paye'];
    }

    /**
     * Anciennete
     * 
     * @param int $id
     * @return int
     */
    public function anciennete($id) {
	$rules = $this->getRule($id);

	return $rules['anciennete'];
    }

    /**
     * Retard, Abscence, Départ Anticipé
     * 
     * @param type $id
     * @return boolean
     */
    public function isLate($id) {
	$id = (int) $id;
	if ($id == self::Absent || $id == self::DepartAnticipe || $id == self::Retard || $id == self::ProblemeRetardDepartAnticipe) {
	    return true;
	}

	return false;
    }

    /**
     * Calcul du temps de retard
     * 
     * @param string $id
     * @param string $in
     * @param string $out
     * @param string $ref
     * @return Array
     */
    public function calculateLateTime($id, $in, $out, $ref) {
	echo "<pre>Paramètres : id = $id, in : $in, out : $out, ref : $ref</pre>";
	echo "<pre>Calcul des heures de retard</pre>";
	$diff	 = '00:00';
	$late	 = false;
	if ((int) $id != self::Retard) {
	    // Ce n'est pas un retard
	    $diff = RHDateTime::diffHours($in, $out);
	    echo "<pre>Compté comme un retard mais il n'y a pas de décompte d'heure</pre>";
	}
	else {
	    // C'est un retard
	    $entree		 = new RHDateTime();
	    $entree->setTime($in);
	    $sortie		 = new RHDateTime();
	    $sortie->setTime($out);
	    $reference	 = new RHDateTime();
	    $reference->setTime($ref);
	    echo "<pre>C'est un code Retard</pre>";
	    if ($reference->isLT($entree)) {
		// Entrée tard
		$late	 = true;
		$diff	 = RHDateTime::diffHours($in, $ref);

		echo "<pre>Il y a retard de $diff</pre>";
	    }
	}

	return array(
	    'diff'	 => $diff,
	    'late'	 => $late,
	);
    }

    public static function calculateLateState($id, $in, $out, $refIn, $refOut) {
	// Valeur de retour
	$state = array(
	    'value'		 => array(
		'diff' => '00:00',
	    ),
	    'retard'	 => array(
		'etat'	 => false,
		'heure'	 => '00:00',
	    ),
	    'departAnticipe' => array(
		'etat'	 => false,
		'heure'	 => '00:00',
	    ),
	);

	// Test du Code PRDA
	if ((int) $id == self::ProblemeRetardDepartAnticipe) {
	    // Traitement
	    // Variable de Temps
	    $entree		 = new RHDateTime();
	    $sortie		 = new RHDateTime();
	    $refEntree	 = new RHDateTime();
	    $refSortie	 = new RHDateTime();

	    // Assignation
	    $entree->setTime($in);
	    $sortie->setTime($out);
	    $refEntree->setTime($refIn);
	    $refSortie->setTime($refOut);

	    // Test Retard
	    if ($refEntree->isLT($entree)) {
		// Retard
		$lateTime	 = RHDateTime::diffHours($refIn, $in);
		$retard		 = array(
		    'etat'	 => true,
		    'heure'	 => $lateTime,
		);
		$state['retard'] = $retard;
	    }

	    // Test Départ Anticipé
	    if ($refSortie->isGT($sortie)) {
		// Départ Anticipé
		$time			 = RHDateTime::diffHours($out, $refOut);
		$departAnticipe		 = array(
		    'etat'	 => true,
		    'heure'	 => $time,
		);
		$state['departAnticipe'] = $departAnticipe;
	    }
	}
	else {
	    // Différence de temps
	    $diff			 = RHDateTime::diffHours($out, $in);
	    $state['value']['diff']	 = $diff;
	}

	return $state;
    }

    /**
     *
     * @param int $code
     * @param int $matricule
     * @param string $entree
     * @param string $sortie
     * @param int $pause
     * @param int $repas
     * @param float $coef
     * @param string $refEntree
     * @param string $refSortie
     * @param array $params
     * @return \RHX\Model\Object\XData
     */
    public function Calcul($code, $matricule, $entree = '00:00', $sortie = '00:00', $pause = 0, $repas = 0, $coef = 0.0, $refEntree = '00:00', $refSortie = '00:00', $params = array()) {
	// Valeur de retour
	$data	 = new XData();
	$code	 = (int) $code;

	switch ($code) {
	    case self::Present:
		// Calcul normal de temps
		$data	 = $this->CalculHeureNormal($matricule, $entree, $sortie, $pause, $repas, $coef);
		break;
	    case self::CongePaye:
		// Calcul mutualisé des calculs de congé
		$data	 = $this->CalculConge($matricule, $coef);
		break;
	    case self::NeTravaillePas:
		// Non Comptabilisé
		break;
	    case self::Indisponible:
		// Non Comptabilisé
		break;
	    case self::Absent:
		// Non Comptabilisé
		break;
	    case self::CongeSansSolde:
		// Non Comptabilisé
		break;
	    case self::TransfertEntrant:
		// Calcul normal
		$data	 = $this->CalculHeureNormal($matricule, $entree, $sortie, $pause, $repas, $coef);
		break;
	    case self::TransfertSortant:
		// Calcul normal
		$data	 = $this->CalculHeureNormal($matricule, $entree, $sortie, $pause, $repas, $coef);
		break;
	    case self::ArretMaladie1:
		break;
	    case self::ArretMaladie2:
		break;
	    case self::AccidentTravail:
		// Calcul sans Pause
		$data	 = $this->CalculHeureSansPause($matricule, $entree, $sortie, $coef);
		break;
	    case self::EcoleFormation:
		// Calcul normal
		// Les horaires sont obligatoires
		$entree	 = '08:00';
		$sortie	 = '15:30';
		$pause	 = 1;
		$repas	 = 1;
		$data	 = $this->CalculHeureNormal($matricule, $entree, $sortie, $pause, $repas, $coef);
		break;
	    case self::Ferie1:
		break;
	    case self::Ferie2:
		break;
	    case self::Fermer:
		// Non Comptabilisé
		break;
	    case self::CongeMaternite:
		// Calcul mutualisé des calculs de congé
		$data	 = $this->CalculConge($matricule, $entree, $sortie, $coef);
		break;
	    case self::DepartAnticipe:
		// Code Obselète
		break;
	    case self::Retard:
		// Code Obselète
		break;
	    case self::ProblemeRetardDepartAnticipe:
		// Calcul Retard et Depart Anticipe
		$data	 = $this->CalculPRDA($matricule, $entree, $sortie, $pause, $repas, $refEntree, $refSortie, $coef);
		break;
	}

	return $data;
    }

    /**
     * Calcul des Congés basés sur les Congés Payés
     * 
     * @param int $matricule
     * @param float $coef
     * @return \RHX\Model\Object\XData
     */
    protected function CalculConge($matricule, $coef) {
	$data			 = new XData();
	// EMployé
	$employeTable		 = new \RHX\Model\Table\EmployeTable($this->adapter);
	$employe		 = $employeTable->get($matricule);
	$avenant		 = $employe->getAvenant();
	$diffValue		 = floatval($avenant->hebdo) / $employe->getNbJourDispo();
	$diff			 = RHDateTime::toTime(number_format($diffValue, 2, ',', ' '));
	$data->tempsDiff	 = $diff;
	$data->tempsValeur	 = $diffValue;
	if ($coef == 0) {
	    $coef = $employe->getCoefficient();
	}
	$data->montant = $data->tempsValeur * floatval($avenant->taux) * $coef;

	return $data;
    }

    /**
     * Calcul normal des heures avec les pauses
     * Pour l'instant les repas ne sont pas pris en compte mais on le marque pour une utilisation ultérieure
     *
     * @param int $matricule
     * @param string $entree
     * @param string $sortie
     * @param int $pause
     * @param int $repas
     * @param float $coef
     * @return \RHX\Model\Object\XData
     */
    protected function CalculHeureNormal($matricule, $entree, $sortie, $pause, $repas, $coef) {
	$data			 = new XData();
	// Différence d'heure
	$diff			 = RHDateTime::diffHours($sortie, $entree);
	$pauseValue		 = $pause * 0.5;
	$pauseTime		 = RHDateTime::toTime(number_format($pauseValue, 2, ',', ' '));
	$data->tempsDiff	 = RHDateTime::diffHours($diff, $pauseTime);
	$data->tempsValeur	 = RHDateTime::toFloat($data->tempsDiff);
	// Employe
	$employeTable		 = new \RHX\Model\Table\EmployeTable($this->adapter);
	$employe		 = $employeTable->get($matricule);
	$avenant		 = $employe->getAvenant();
	if ($coef == 0) {
	    // On prend le coefficient par défaut de l'employé
	    $coef = $employe->getCoefficient();
	}
	$data->montant = $data->tempsValeur * floatval($avenant->taux) * $coef;

	// Debogage
//	$this->logger->debug("Calcul Heure Normal");
//	$this->logger->debug("Paramètres : Matricule ($matricule), Entrée ($entree), Sortie ($sortie), Pause ($pause), Repas ($repas), Coefficient ($coef)");
//	$this->logger->debug('Données en retour : ');
//	$this->logger->debug(json_encode($data));

	return $data;
    }

    /**
     * Calcul ne prenant pas en compte les pauses et repas
     *
     * @param int $matricule
     * @param string $entree
     * @param string $sortie
     * @param float $coef
     * @return \RHX\Model\Object\XData
     */
    protected function CalculHeureSansPause($matricule, $entree, $sortie, $coef) {
	$data			 = new XData();
	// Différence d'heure
	$diff			 = RHDateTime::diffHours($sortie, $entree);
	$data->tempsDiff	 = $diff;
	$data->tempsValeur	 = RHDateTime::toFloat($diff);
	// Employe
	$employeTable		 = new \RHX\Model\Table\EmployeTable($this->adapter);
	$employe		 = $employeTable->get($matricule);
	$avenant		 = $employe->getAvenant();
	if ($coef == 0) {
	    // On prend le coefficient par défaut
	    $coef = $employe->getCoefficient();
	}
	$data->montant = $data->tempsValeur * floatval($avenant->taux) * $coef;

	// Debogage
//	$this->logger->debug("Calcul Heure Sans Pause");
//	$this->logger->debug("Paramètres : Matricule ($matricule), Entrée ($entree), Sortie ($sortie), Coefficient ($coef)");
//	$this->logger->debug('Données en retour : ');
//	$this->logger->debug(json_encode($data));

	return $data;
    }

    /**
     * Calcul des horaires pour les retards
     * 
     * @param int $matricule
     * @param string $entree
     * @param string $sortie
     * @param int $pause
     * @param int $repas
     * @param string $refEntree
     * @param string $refSortie
     * @param float $coef
     * @return \RHX\Model\Object\XData
     */
    protected function CalculPRDA($matricule, $entree, $sortie, $pause, $repas, $refEntree, $refSortie, $coef) {
	// Valeur de retour
	$data = new XData();

	// Variables temporelles
	$in	 = new RHDateTime();
	$out	 = new RHDateTime();
	$refIn	 = new RHDateTime();
	$refOut	 = new RHDateTime();

	// Assignation
	$in->setTime($entree);
	$out->setTime($sortie);
	$refIn->setTime($refEntree);
	$refOut->setTime($refSortie);

	// Test de retard
	if ($refIn->isLT($in)) {
	    $data->retard		 = true;
	    $data->tempsRetard	 = RHDateTime::diffHours($refEntree, $entree);
	}

	// Test de départ anticipé
	if ($refOut->isGT($out)) {
	    $data->anticipe		 = true;
	    $data->tempsAnticipe	 = RHDateTime::diffHours($sortie, $refSortie);
	}

	$dataNormal		 = $this->CalculHeureNormal($matricule, $entree, $sortie, $pause, $repas, $coef);
	$data->tempsDiff	 = $dataNormal->tempsDiff;
	$data->tempsValeur	 = $dataNormal->tempsValeur;
	$data->montant		 = $dataNormal->montant;

	// Debogage
//	$this->logger->debug("Calcul Heure dans PRDA");
//	$this->logger->debug("Paramètres : Matricule ($matricule), Entrée ($entree), Sortie ($sortie), Pause ($pause), Repas ($repas), Reférence d'Entree ($refEntree), Reférence de Sortie ($refSortie), Coefficient ($coef)");
//	$this->logger->debug('Données en retour : ');
//	$this->logger->debug(json_encode($data));

	return $data;
    }

    /**
     * Vérification de l'heure et de la validité des pauses et repas
     * 
     * @param string $in
     * @param string $out
     * @return array
     */
    public static function verifyHour($in, $out) {
	$result = array(
	    'pause'	 => false, 'repas'	 => false,
	);
	if ($in == $out) {
	    return $result;
	}
	$entree	 = new RHDateTime();
	$sortie	 = new RHDateTime();
	$entree->setTime($in);
	$sortie->setTime($out);
	
	$diff	 = '00:00';
	if ($entree->isLT($sortie)) {
	    $diff = RHDateTime::diffHours($out, $in);
	}
	$diffTime	 = new RHDateTime();
	$diffTime->setTime($diff);
	$refDuree	 = new RHDateTime();
	$refDuree->setTime('05:00');
	if ($diffTime->isGT($refDuree)) {
	    $result['pause'] = true;
	}
	$h12	 = new RHDateTime();
	$h12->setTime('12:00');
	$h14	 = new RHDateTime();
	$h14->setTime('14:00');
	if ($h12->isBetween($entree, $sortie) || $h14->isBetween($entree, $sortie)) {
	    $result['repas'] = true;
	}

	return $result;
    }

}

?>
